// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0

import { ChildIndicator, NameLabel, ResettingLineEdit, SecondaryContent } from "./basics.slint";
import { ColorMainContent, RgbaColorSliders } from "./color-basics.slint";
import { GradientMainContent } from "./gradient-basics.slint";

import { Api, BrushKind, ColorData, GradientStop, PropertyValue, PropertyValueKind } from "../../api.slint";
import { EditorSpaceSettings } from "../../components/styling.slint";

import { ComboBox, Palette } from "std-widgets.slint";

export component BrushWidget inherits GridLayout {
    in property <bool> enabled;
    in property <string> property-name;
    in property <PropertyValue> property-value;
    in property <bool> has-code-action <=> sub.has-code-action;
    in property <bool> has-reset-action <=> sub.has-reset-action;

    callback code-action();
    callback reset-action();

    callback test-brush-binding(kind: BrushKind, angle: float, color: color, stops: [GradientStop]) -> bool;
    callback set-brush-binding(kind: BrushKind, angle: float, color: color, stops: [GradientStop]);

    private property <color> current-color;
    private property <brush> current-brush;
    private property <[GradientStop]> current-gradient-stops;
    private property <ColorData> current-color-data: Api.color-to-data(self.current-color);
    private property <BrushKind> current-brush-kind;
    private property <float> current-angle;

    spacing-vertical: EditorSpaceSettings.default-spacing;
    width: 100%;

    function update-brush() {
        // Always use the angle we expect in the preview!
        root.current-brush = Api.create-brush(root.current-brush-kind, 90.0, root.current-color, root.current-gradient-stops);
        root.test-brush-binding(root.current-brush-kind, root.current-angle, root.current-color, root.current-gradient-stops);
    }

    function apply-value() {
        root.current-color = self.property-value.value-brush;
        root.current-color-data = Api.color-to-data(self.property-value.value-brush);
        root.current-brush;
        root.current-brush-kind = self.property-value.brush-kind;
        root.current-gradient-stops = self.property-value.gradient-stops;
        root.current-angle = self.property-value.value-float;

        kind_cb.current-index = self.property-value.brush-kind == BrushKind.solid ?
            0 : self.property-value.brush-kind == BrushKind.linear ? 1 : 2;

        angle.text = root.current-angle;
    }

    private property <bool> has-focus: color_main.has-focus || grad_main.has-focus || sliders.has-focus || angle.has-focus;

    function test-color(text: string) -> bool {
        if self.current-brush-kind != BrushKind.solid && grad_main.selected-index >= 0 {
            self.current-gradient-stops[grad_main.selected-index].color = root.current-color;
            self.update-brush();
            return true;
        } else if self.current-brush-kind == BrushKind.solid {
            return root.test-brush-binding(root.current-brush-kind, root.current-angle, root.current-color, root.current-gradient-stops);
        }
        return true;
    }

    function set-color(text: string) {
        root.current-color = Api.string-to-color(text);
        root.set-brush-binding(root.current-brush-kind, root.current-angle, root.current-color, root.current-gradient-stops);
    }


    init => {
        apply-value();
        update-brush();
    }

    changed has-focus => {
        if !self.has-focus {
            apply-value();
            update-brush();
        }
    }

    changed property-value => {
        if self.property-value.kind != PropertyValueKind.color && self.property-value.kind != PropertyValueKind.brush {
            return;
        }

        if !self.has-focus {
            apply-value();
            update-brush();
        }
    }

    Row {
        NameLabel {
            col: 1;

            property-name: root.property-name;
            property-value: root.property-value;
        }
    }

    Row {
        kind_cb := ComboBox {
            col: 1;

            model: [ "Solid Color", "Linear Gradient", "Radial Gradient"];

            changed current-index => {
                if self.current-index == 0 {
                    root.current-brush-kind = BrushKind.solid;
                } else if self.current-index == 1 {
                    root.current-brush-kind = BrushKind.linear;
                } else {
                    root.current-brush-kind = BrushKind.radial;
                }

                root.update-brush();
            }
        }
    }

    Row {
        childIndicator := ChildIndicator {
            horizontal-stretch: 0;
            control-hover: kind_cb.has-focus || grad_main.has-focus || color_main.has-focus;
        }

        VerticalLayout {
            Rectangle {
                clip: true;
                height: root.current-brush-kind == BrushKind.solid ? color_main.preferred-height : 0px;

                color_main := ColorMainContent {
                    current-color <=> root.current-color;
                    enabled <=> root.enabled;

                    set-color-binding(text) => {
                        root.set-brush-binding(root.current-brush-kind, root.current-angle, root.current-color, root.current-gradient-stops);
                    }
                    test-color-binding(text) => {
                        return root.test-brush-binding(root.current-brush-kind, root.current-angle, root.current-color, root.current-gradient-stops);
                    }
                }
            }

            Rectangle {
                clip: true;
                height: root.current-brush-kind != BrushKind.solid ? grad_main.preferred-height : 0px;

                grad_main := GradientMainContent {
                    current-brush-kind <=> root.current-brush-kind;
                    current-color <=> root.current-color;
                    current-brush <=> root.current-brush;
                    gradient-stops: root.current-gradient-stops;

                    update-brush() => {
                        root.update-brush();
                    }
                }
            }
        }
    }

    Row {
        sub := SecondaryContent {
            col: 1;

            open: childIndicator.open;

            Rectangle {
                clip: true;
                height: root.current-brush-kind == BrushKind.linear ? self.preferred-height : 0px;

                HorizontalLayout {
                    spacing: EditorSpaceSettings.default-spacing;
                    Text {
                        text: "Angle:";
                        vertical-alignment: center;
                    }

                    angle := ResettingLineEdit {
                        enabled <=> root.enabled;

                        input-type: decimal;

                        edited(text) => {
                            self.can-compile = text.is-float() && root.test-brush-binding(root.current-brush-kind, text.is-empty ? 0.0 : text.to-float(), root.current-color, root.current-gradient-stops);
                            if self.can-compile {
                                root.current-angle = text.is-empty ? 0.0 : text.to-float();
                                root.update-brush();
                            }
                        }

                        accepted(text) => {
                            root.set-brush-binding(root.current-brush-kind, root.current-angle, root.current-color, root.current-gradient-stops);
                            update-brush();
                        }
                    }

                    Rectangle {
                        Image {
                            source: @image-url("../../assets/dial.svg");
                            height: 30px;
                            rotation-angle: root.current-angle * 1deg;
                            colorize: Palette.foreground.transparentize(0.8);
                        }
                        TouchArea {
                            private property <length> x-pos;
                            private property <length> y-pos;

                            moved() => {
                                self.x-pos = self.mouse-x - (self.width / 2);
                                self.y-pos = -1.0 * (self.mouse-y - (self.height / 2));
                                root.current-angle = Math.atan2(self.x-pos / 1px, self.y-pos / 1px) / 1deg;
                                root.update-brush();
                                angle.text = root.current-angle;
                            }
                        }
                    }
                }
            }

            sliders := RgbaColorSliders {
                enabled: root.enabled && (root.current-brush-kind == BrushKind.solid || grad_main.selected-index >= 0);
                current-color <=> root.current-color;

                set-color-binding(text) => {
                    root.set-brush-binding(root.current-brush-kind, root.current-angle, root.current-color, root.current-gradient-stops);
                }
                test-color-binding(text) => {
                    return root.test-color(text);
                }
            }

            code-action() => {
                root.code-action();
            }
            reset-action() => {
                root.reset-action();
            }
        }
    }
}

